home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mgr_2 / src / atari / line.c < prev    next >
C/C++ Source or Header  |  1990-09-17  |  6KB  |  218 lines

  1. /*                        Copyright (c) 1989 Bellcore
  2.  *                            All Rights Reserved
  3.  *       Permission is granted to copy or use this program, EXCEPT that it
  4.  *       may not be sold for profit, the copyright notice must be reproduced
  5.  *       on copies, and credit should be given to Bellcore where it is due.
  6.  *       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
  7.  */
  8. /*    $Header: line.c,v 1.3 89/05/25 07:51:36 sau Locked $
  9.     $Source: /usr/u/sau/mgr/src/dec/RCS/line.c,v $
  10. */
  11. static char    RCSid_[] = "$Source: /usr/u/sau/mgr/src/dec/RCS/line.c,v $$Revision: 1.3 $";
  12.  
  13. #include "bitmap.h"
  14. #ifdef atarist
  15. #include <linea.h>
  16. #endif
  17.  
  18. /*  Draw a line  - Bresenham method , portable Bitblt version (S. A. Uhler)
  19.  */
  20.  
  21. bit_line(dest, x0, y0, x1, y1, func)
  22. register BITMAP *dest;                /* destination bitmap */    
  23. int x0, y0, x1, y1;                    /* line coordinates */
  24. int func;                                /* set, clear, or invert */
  25.    {
  26.    register unsigned bit;            /* bit offset in current word */
  27.    register DATA *dst;                /* current word in bitmap */
  28.     register int count;                /* current x position in loop */
  29.     register int err;                    /* accumulated error */
  30.    register int d_incr;                /* words to next scan line */
  31.    register int rincr, rdecr;
  32.    int dx, dy;                            /* # of pixels in x and y */
  33.    int temp;
  34.  
  35.    /* clip here */
  36.  
  37. #ifndef NOCLIP
  38.  
  39. #define TOP    001
  40. #define BOTTOM    002
  41. #define LEFT    004
  42. #define RIGHT    010
  43. #define CROSS(x,y) \
  44.       (x<0 ? LEFT : x>= (dest->wide) ? RIGHT : 0) + \
  45.       (y < 0 ? TOP : y >=  (dest -> high) ? BOTTOM : 0)
  46.  
  47.       {
  48.  
  49.       /* The classic line clipping algorithm */
  50.         /* (I don't remember anymore where I got it from, sorry -sau) */
  51.  
  52.       register int cross0 = CROSS(x0, y0);
  53.       register int cross1 = CROSS(x1, y1);
  54.  
  55.       while (cross0 || cross1) {
  56.           int cross, x, y;
  57.           if (cross0 & cross1)
  58.              return;
  59.           if (cross0 != 0)
  60.              cross = cross0;
  61.           else
  62.              cross = cross1;
  63.           if (cross & (LEFT | RIGHT)) {
  64.              int edge = (cross & LEFT) ? 0 : dest->wide - 1;
  65.              y = y0 + (y1 - y0) * (edge - x0) / (x1 - x0);
  66.              x = edge;
  67.              }
  68.           else if (cross & (TOP | BOTTOM)) {
  69.              int edge = (cross & TOP) ? 0 : dest->high - 1;
  70.              x = x0 + (x1 - x0) * (edge - y0) / (y1 - y0);
  71.              y = edge;
  72.              }
  73.           if (cross == cross0) {
  74.              x0 = x;
  75.              y0 = y;
  76.              cross0 = CROSS(x, y);
  77.              }
  78.           else {
  79.              x1 = x;
  80.              y1 = y;
  81.              cross1 = CROSS(x, y);
  82.              }
  83.          }
  84.       }
  85.  
  86.    /* end of clipping */
  87.  
  88. #endif
  89.  
  90.    x0 += dest->x0;
  91.    y0 += dest->y0;
  92.    x1 += dest->x0;
  93.    y1 += dest->y0;
  94.  
  95.    /* always draw left to right */
  96.  
  97.    if (x1 < x0) {
  98.       temp = x1, x1 = x0, x0 = temp;
  99.       temp = y1, y1 = y0, y0 = temp;
  100.       }
  101.    dx = x1 - x0;
  102.    dy = y1 - y0;
  103.  
  104. #ifdef INVERT
  105.     /* invert all raster ops */
  106.  
  107.     func = op_invert[15&func];
  108. #endif
  109.  
  110. #ifdef atarist
  111.    if (IS_SCREEN(dest)) {
  112.     __aline->_X1 = x0; __aline->_Y1 = y0;
  113.     __aline->_X2 = x1; __aline->_Y2 = y1;
  114.     __aline->_COLBIT0 =
  115.     __aline->_COLBIT1 = __aline->_COLBIT1 = __aline->_COLBIT3 = 0xf;
  116.     __aline->_LNMASK = 0xffff;
  117.     __aline->_LSTLIN = 0xffff;
  118.     switch(OPCODE(func)) {
  119.         case OPCODE(SRC):
  120.         case OPCODE(SRC | DST):
  121.         case OPCODE(SRC | ~DST):
  122.         case OPCODE(~0):
  123.             __aline->_WMODE = 0;
  124.             break;
  125.         case OPCODE(~SRC):
  126.         case OPCODE(~(SRC|DST)):
  127.         case OPCODE(DST & ~SRC):
  128.         case OPCODE(0):
  129.             __aline->_LNMASK = 0;
  130.             __aline->_WMODE = 0;
  131.             break;
  132.         case OPCODE(SRC ^ DST):
  133.         case OPCODE(~DST):
  134.         case OPCODE(SRC & ~DST):
  135.         case OPCODE(~(SRC&DST)):
  136.             __aline->_WMODE = 2;
  137.             break;
  138.         default:
  139.             return;
  140.         }
  141.         linea3();        /* draw line on screen */
  142.         return;
  143.     }
  144. #endif
  145.  
  146.    d_incr = BIT_LINE(dest);
  147.    dst = y0 * d_incr + (x0>>LOGBITS) +  (dest->data);
  148.    bit = GETLSB(MSB,(x0&BITS));
  149.  
  150.    if (dy <= 0)
  151.       d_incr = -d_incr, dy = -dy;
  152.  
  153. #define XMOVE if ((bit=GETLSB(bit,1))==0) {bit = MSB; dst++;}
  154. #define YMOVE dst += d_incr
  155.  
  156. #define STEP(dx,dy,xmove,ymove,op) {        \
  157.     rincr = (dx - dy)<<1;            \
  158.     rdecr = -(dy<<1);                \
  159.     err = dx + rdecr;                \
  160.     for (count = dx; count >= 0; count--) {    \
  161.         op;                        \
  162.         xmove;                        \
  163.         if (err < 0) {                \
  164.             ymove;                \
  165.             err += rincr;                \
  166.             }                    \
  167.         else {                    \
  168.             err += rdecr;                \
  169.             }                    \
  170.         }                     \
  171.     }
  172.  
  173.    if (dx > dy) {            /* gentle slope (this could be made faster) */
  174.       switch (OPCODE(func)) {
  175.           case OPCODE(SRC):
  176.           case OPCODE(SRC | DST):
  177.           case OPCODE(SRC | ~DST):
  178.           case OPCODE(~0):
  179.               STEP(dx, dy, XMOVE, YMOVE, *dst |= bit);                /* set */
  180.              break;
  181.           case OPCODE(~SRC):
  182.           case OPCODE(~(SRC|DST)):
  183.           case OPCODE(DST & ~SRC):
  184.           case OPCODE(0):
  185.               STEP(dx, dy, XMOVE, YMOVE, *dst &= ~bit);        /* clear */
  186.              break;
  187.           case OPCODE(SRC ^ DST):
  188.           case OPCODE(~DST):
  189.           case OPCODE(SRC & ~DST):
  190.           case OPCODE(~(SRC&DST)):
  191.               STEP(dx, dy, XMOVE, YMOVE, *dst ^= bit);        /* invert */
  192.              break;
  193.          }
  194.       }
  195.    else    {            /* steep slope */
  196.       switch (OPCODE(func)) {
  197.           case OPCODE(SRC):
  198.           case OPCODE(SRC | DST):
  199.           case OPCODE(SRC | ~DST):
  200.           case OPCODE(~0):
  201.               STEP(dy, dx, YMOVE, XMOVE, *dst |= bit);                /* set */
  202.              break;
  203.           case OPCODE(~SRC):
  204.           case OPCODE(~(SRC|DST)):
  205.           case OPCODE(DST & ~SRC):
  206.           case OPCODE(0):
  207.               STEP(dy, dx, YMOVE, XMOVE, *dst &= ~bit);            /* clear */
  208.              break;
  209.           case OPCODE(SRC ^ DST):
  210.           case OPCODE(~DST):
  211.           case OPCODE(SRC & ~DST):
  212.           case OPCODE(~(SRC&DST)):
  213.               STEP(dy, dx, YMOVE, XMOVE, *dst ^= bit);                /* invert */
  214.              break;
  215.          }
  216.        }
  217.    }
  218.